package main

import "fmt"

// 给你一个链表的头节点 head ，判断链表中是否有环。
// 如果链表中有某个节点，可以通过连续跟踪 next 指针再次到达，则链表中存在环。
// 为了表示给定链表中的环，评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置（索引从 0 开始）。注意：pos 不作为参数进行传递 。
// 仅仅是为了标识链表的实际情况。
func main() {
	e := &ListNode{
		Val:  2,
		Next: nil,
	}
	head := &ListNode{
		Val:  1,
		Next: e,
	}

	e.Next = head

	fmt.Println(hasCycle1(head))
}

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func hasCycle(head *ListNode) bool {
	if head == nil {
		return false
	}

	m := make(map[*ListNode]struct{})
	m[head] = struct{}{}
	n := head.Next
	for {
		if n == nil {
			return false
		}

		if _, ok := m[n]; ok {
			return true
		} else {
			m[n] = struct{}{}
		}

		n = n.Next
	}
}

// 快慢指针
// 如果存在环的快慢指针一定会在环上相遇，如果快慢指针相遇说明存在环
func hasCycle1(head *ListNode) bool {
	l := head
	f := head
	for f != nil && f.Next != nil {
		f = f.Next
		if l == f {
			return true
		}

		f = f.Next
		if f == nil {
			return false
		}

		l = l.Next
	}

	return false
}

type ListNode struct {
	Val  int
	Next *ListNode
}
